/**
* AutoSWF - Cody Cushing. March 26, 2009
* Copyright (c) 2009 Cody Cushing
* No use restrictions. Maintain this notice in all versions. 
**/

package com.autoswf.core
{
	import flash.events.Event;
	
	import flexunit.framework.TestCase;

	public class SpriteChainLinkTest extends TestCase
	{
		private var spriteChainLink:SpriteChainLink;
		private var mockLink1:MockChainLink;
		private var mockLink2:MockChainLink;
		
		public function SpriteChainLinkTest(methodName:String=null)
		{
			super(methodName);
		}
		
		override public function setUp():void
		{
			mockLink1 = new MockChainLink("mockLink1");
			mockLink2 = new MockChainLink("mockLink2")
			spriteChainLink = new SpriteChainLink("testLink");
		}

		public function testGetId():void
		{
			assertEquals("cannot access id", "testLink", spriteChainLink.id);
		}
		
		/**
		 * Tests that a SpriteLink behaves like a normal Link when passing info down.
		 */		
		public function testSendDownChain():void
		{
			spriteChainLink.addChildLink(mockLink1);
			spriteChainLink.sendDownChain(new Transport("mockLink1->message"));
			
			assertEquals("did not resolve properly targeted", "message", mockLink1.sendDownChainResult);
		}
		
		/**
		 * Tests that a handler can be invoked from somewhere up the chain.
		 */		
		public function testSendDownChainInvokesRegisteredListener():void
		{
			var successHandler:Function = function():void {	};
			var timeoutFn:Function = function():void
			{
				fail("failed to automate event");
			}
			
			spriteChainLink.addTrackingEventListener("mockEventType", addAsync(successHandler, 100, null, timeoutFn))
			spriteChainLink.addChildLink(mockLink1);
			spriteChainLink.sendDownChain(new Transport(new Event("mockEventType")));
		}
		
		/**
		 * Tests generic functionality of hasEventListener
		 */		
		public function testHasTrackEventListener():void
		{
			spriteChainLink.addTrackingEventListener("event", new Function);
			assertTrue("didnt indicate registered event", spriteChainLink.hasTrackingEventListener("event"));
		}
		
		/**
		 * Tests extended functionality of hasEventListener (ternary foo with dictionaries for optional 
		 * function checking can be buggy).
		 */		
		public function testHasTrackEventListenerThrowsError():void
		{
			var flag:Boolean = false;
			try
			{
				spriteChainLink.hasTrackingEventListener("event", new Function)
			}
			catch(error:Error)
			{
				flag = true;
			}
			assertFalse("check listener with function throws error on null dictionary", flag);
		}
		
		/**
		 * Tests that a removed listener gets nuked.
		 */		
		public function testRemoveTrackEventListener():void
		{
			var testFn:Function = function():void
			{
				assertTrue("function invoked after listener was removed", false);
			}
			spriteChainLink.addTrackingEventListener("mockEventType", testFn);
			spriteChainLink.removeTrackingEventListener("mockEventType", testFn);
			spriteChainLink.sendDownChain(new Transport(new Event("mockEventType")));
			
			assertFalse("false positive on removed event", spriteChainLink.hasTrackingEventListener("mockEventType"));
		}

		/**
		 * Tests that this doesnt throw an error. 
		 */		
		public function testRemoveTrackEventListenerThatWasNotAdded():void
		{
			var fakeFn:Function = function():void {};
			var flag:Boolean = false;
			try
			{
				spriteChainLink.removeTrackingEventListener("mockEventType", fakeFn);
			}
			catch(error:Error)
			{
				flag = true;
			}
			assertFalse(flag);
		}
		
		/**
		 * Tests that an event type can have multiple listeners, and they can be removed seperately
		 */		
		public function testRemoveOneOfMultipleListenersForEventType():void
		{
			var flag1:Boolean = false;
			var func1:Function = function():void 
			{
				flag1 = true;
			}
			var flag2:Boolean = true;
			var func2:Function = function():void 
			{
				flag2 = false;
			}

			spriteChainLink.addTrackingEventListener("mockEventType", func1);
			spriteChainLink.addTrackingEventListener("mockEventType", func2);
			spriteChainLink.removeTrackingEventListener("mockEventType", func2);

			spriteChainLink.sendDownChain(new Transport(new Event("mockEventType")));

			assertTrue(flag1 && flag2);
		}
		
		/**
		 * Tests that both listeners for one event type get invoked.  
		 */		
		public function testMultipleListenersForOneEventType():void
		{
			var flag1:Boolean = false;
			var func1:Function = function():void 
			{
				flag1 = true;
			}
			var flag2:Boolean = false;
			var func2:Function = function():void 
			{
				flag2 = true;
			}
			spriteChainLink.addTrackingEventListener("mockEventType", func1);
			spriteChainLink.addTrackingEventListener("mockEventType", func2);
			
			spriteChainLink.sendDownChain(new Transport(new Event("mockEventType")));

			assertTrue(flag1 && flag2);
		}
	}
}

